package com.itfitness.cameraxfilterdemo;

import android.Manifest;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.media.Image;
import android.media.MediaScannerConnection;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;

import androidx.camera.core.AspectRatio;
import androidx.camera.core.Camera;
import androidx.camera.core.CameraSelector;
import androidx.camera.core.ImageAnalysis;
import androidx.camera.core.ImageProxy;
import androidx.camera.core.Preview;
import androidx.camera.core.UseCase;
import androidx.camera.core.impl.MutableOptionsBundle;
import androidx.camera.lifecycle.ProcessCameraProvider;
import androidx.camera.view.PreviewView;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.core.view.ViewCompat;
import androidx.fragment.app.FragmentActivity;
import androidx.lifecycle.LifecycleOwner;

import com.atomcloud.yuv.YuvUtils;
import com.atomcloud.yuv.entities.YuvFrame;
import com.blankj.utilcode.util.ImageUtils;
import com.google.common.util.concurrent.ListenableFuture;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import jp.co.cyberagent.android.gpuimage.GPUImage;
import jp.co.cyberagent.android.gpuimage.filter.GPUImageFilter;
import jp.co.cyberagent.android.gpuimage.util.FileUtils;
import jp.co.cyberagent.android.gpuimage.util.GPUImageFilterTools;

import static java.util.concurrent.Executors.newSingleThreadExecutor;

public class GpuFilterCameraActivity extends FragmentActivity implements View.OnClickListener,ImageAnalysis.Analyzer {

    private String TAG = GpuFilterCameraActivity.class.getSimpleName();
    private GPUImageFilterTools.FilterAdjuster mFilterAdjuster;
    private GPUImageFilterTools filterTools = new GPUImageFilterTools();
    private Context context;

    private ExecutorService cameraExecutor;
    private YuvUtils yuvUtils =new YuvUtils();
    private Bitmap bitmap;
    private GPUImage gpuImage;
    private boolean isTakePhoto = false;
    PreviewView viewFinder;
    ImageView takepicture;
    ImageView imageView;
    TextView changeFilter;
    ImageView switchCamera;
    private int cameraType = 0;
    private GPUImageFilter mNoImageFilter = new GPUImageFilter();
    private GPUImageFilter mCurrentImageFilter = mNoImageFilter;
    private int REQUEST_CODE_PERMISSIONS = 10;
    private String[] REQUIRED_PERMISSIONS = new String[]{Manifest.permission.CAMERA,Manifest.permission.WRITE_EXTERNAL_STORAGE};

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_gpu_camera_filter);
        context = this;
        initView();
        initFilter();
        takepicture.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                isTakePhoto = true;
            }
        });
        cameraExecutor = newSingleThreadExecutor();
        // Request camera permissions
        if (allPermissionsGranted()) {
            startCamera();
        } else {
            ActivityCompat.requestPermissions(
                    this, REQUIRED_PERMISSIONS, REQUEST_CODE_PERMISSIONS
            );
        }

        changeFilter.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                changeFilter();
            }
        });
        switchCamera.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if(cameraType == 0){
                    changeCamera();
                    cameraType = 1;
                }else{
                    startCamera();
                    cameraType = 0;
                }
            }
        });

        startCamera();
    }

    private void initView() {
        viewFinder = findViewById(R.id.viewFinder);
        takepicture = findViewById(R.id.bt_takepicture);
        imageView = findViewById(R.id.imageView);
        changeFilter = findViewById(R.id.filter_name_tv);
        switchCamera = findViewById(R.id.switch_camera_iv);
        findViewById(R.id.close_iv).setVisibility(View.VISIBLE);
        findViewById(R.id.close_iv).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                onBackPressed();
            }
        });

        getPermissionsGranted();
    }

    private GPUImageFilterTools.OnGpuImageFilterChosenListener mOnGpuImageFilterChosenListener = new GPUImageFilterTools.OnGpuImageFilterChosenListener() {
        @Override
        public void progressChanged(int progress) {
            if (mFilterAdjuster != null) {
                mFilterAdjuster.adjust(progress);
            }
            gpuImage.requestRender();
        }
        @Override
        public void onGpuImageFilterChosenListener(GPUImageFilter gpuImageFilter) {
            switchFilterTo(gpuImageFilter);
        }
    };

    private void switchFilterTo(GPUImageFilter filter) {
        if (mCurrentImageFilter == null
                || (filter != null && !mCurrentImageFilter.getClass().equals(filter.getClass()))) {
            mCurrentImageFilter = filter;
            gpuImage.setFilter(mCurrentImageFilter);
            mFilterAdjuster = new GPUImageFilterTools.FilterAdjuster(mCurrentImageFilter);
        }
    }

    private void initFilter() {
        gpuImage = new GPUImage(this);
    }

    private void changeFilter(){
        filterTools.showDialog(this, mOnGpuImageFilterChosenListener);
    }



    private boolean allPermissionsGranted(){
        if(ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED){
            return true;
        }else{
            return false;
        }
    }


    private void getPermissionsGranted(){

    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] paramArrayOfInt) {
        super.onRequestPermissionsResult(requestCode, permissions, paramArrayOfInt);
        if (requestCode == REQUEST_CODE_PERMISSIONS) {
            if (allPermissionsGranted()) {
                startCamera();
            } else {

            }
        }
    }



    private void startCamera() {
        final ListenableFuture cameraProviderFuture = ProcessCameraProvider.getInstance(context);
        cameraProviderFuture.addListener(() -> {
            ProcessCameraProvider cameraProvider= null;
            try {
                cameraProvider = (ProcessCameraProvider) cameraProviderFuture.get();
                Preview preview = new Preview.Builder().build();
                preview.setSurfaceProvider(viewFinder.getSurfaceProvider());
                ImageAnalysis imageAnalyzer = new ImageAnalysis.Builder().setTargetAspectRatio(AspectRatio.RATIO_16_9).build();;
                imageAnalyzer.setAnalyzer(cameraExecutor, (ImageAnalysis.Analyzer)GpuFilterCameraActivity.this);
                CameraSelector cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA;;
                cameraProvider.unbindAll();
                cameraProvider.bindToLifecycle(GpuFilterCameraActivity.this, cameraSelector, new UseCase[]{preview, imageAnalyzer});

            } catch (Exception e) {
                e.printStackTrace();
            }
        }, ContextCompat.getMainExecutor(this));
    }

    private void changeCamera() {
        final ListenableFuture cameraProviderFuture = ProcessCameraProvider.getInstance(context);
        cameraProviderFuture.addListener(() -> {
            ProcessCameraProvider cameraProvider= null;
            try {
                cameraProvider = (ProcessCameraProvider) cameraProviderFuture.get();
                Preview preview = new Preview.Builder().build();
                preview.setSurfaceProvider(viewFinder.getSurfaceProvider());
                ImageAnalysis imageAnalyzer = new ImageAnalysis.Builder().setTargetAspectRatio(AspectRatio.RATIO_16_9).build();;
                imageAnalyzer.setAnalyzer(cameraExecutor, (ImageAnalysis.Analyzer)GpuFilterCameraActivity.this);
                CameraSelector cameraSelector = CameraSelector.DEFAULT_FRONT_CAMERA;;
                cameraProvider.unbindAll();
                cameraProvider.bindToLifecycle(GpuFilterCameraActivity.this, cameraSelector, new UseCase[]{preview, imageAnalyzer});
            } catch (Exception e) {
                e.printStackTrace();
            }
        }, ContextCompat.getMainExecutor(this));
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        cameraExecutor.shutdown();
    }

    @Override
    @SuppressLint("UnsafeOptInUsageError")
    public void analyze(ImageProxy image) {
        if(!isTakePhoto){
            //将Android的YUV数据转为libYuv的数据
            @SuppressLint("UnsafeOptInUsageError")
            YuvFrame yuvFrame = yuvUtils.convertToI420(image.getImage());
            //对图像进行旋转（由于回调的相机数据是横着的因此需要旋转90度）
            yuvFrame = yuvUtils.rotate(yuvFrame, 90);
            //根据图像大小创建Bitmap
            bitmap = Bitmap.createBitmap(yuvFrame.getWidth(), yuvFrame.getHeight(), Bitmap.Config.ARGB_8888);
            //将图像转为Argb格式的并填充到Bitmap上
            yuvUtils.yuv420ToArgb(yuvFrame,bitmap);
            //利用GpuImage给图像添加滤镜
            bitmap = gpuImage.getBitmapWithFilterApplied(bitmap);
            //由于这不是UI线程因此需要在UI线程更新UI
            imageView.post(new Runnable() {
                @Override
                public void run() {
                    imageView.setImageBitmap(bitmap);
                    if(isTakePhoto){
                        takePhoto();
                    }
                    //关闭ImageProxy，才会回调下一次的数据
                    image.close();
                }
            });
        }else{
            image.close();
        }
    }


    /**
     * 拍照
     */
    private void takePhoto() {
        filterTools.showDialog(this, mOnGpuImageFilterChosenListener);
//        Thread{
//            val filePath = File(getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS),"${System.currentTimeMillis()}save.png")
//            ImageUtils.save(bitmap,filePath.absolutePath,Bitmap.CompressFormat.PNG)
//            ToastUtils.showShort("拍摄成功")
//            isTakePhoto = false
//        }.start()
    }

    @Override
    public void onClick(View view) {

    }
}
